import datetime
import os
import sys
from contextlib import asynccontextmanager
from fastapi import FastAPI, HTTPException, Body, Depends
from fastapi.responses import StreamingResponse, JSONResponse
from pydantic import BaseModel, Field, ValidationError
from typing import Dict, Any, List, Literal, Union
import io
import openpyxl
import glob
import locale
import urllib.parse
from starlette.responses import Response
from qcloud_cos import CosConfig, CosS3Client, CosServiceError
from fastapi.staticfiles import StaticFiles
from fastapi.middleware.cors import CORSMiddleware

from src.config import settings
from src.dependencies.cos_client import init_cos_client
from src.api import api_router
from src.utils.logger import logger

# 全局变量，用于存储 COS 客户端实例
# 注意：在 FastAPI 中，我们通常会通过依赖注入来传递客户端，而不是直接使用全局变量
# 但为了兼容你之前的代码结构，我们先保留全局变量，后续会展示依赖注入的方式
cos_client_instance: CosS3Client = None

@asynccontextmanager
async def lifespan(app: FastAPI):
    # 启动时的代码
    try:
        init_cos_client()
        logger.info("COS client initialized successfully")
    except Exception as e:
        logger.error(f"Failed to initialize COS client: {e}")
        raise e

    logger.info("--- Environment Variables at Startup ---")
    logger.info(f"LANG: {os.getenv('LANG')}")
    logger.info(f"LC_ALL: {os.getenv('LC_ALL')}")
    logger.info(f"PYTHONIOENCODING: {os.getenv('PYTHONIOENCODING')}")
    logger.info(f"sys.getdefaultencoding(): {sys.getdefaultencoding()}")
    logger.info(f"sys.getfilesystemencoding(): {sys.getfilesystemencoding()}")
    logger.info("--------------------------------------")
    yield
    # 关闭时的代码（如果需要的话）
    pass

app = FastAPI(
    title="Excel Filler API",
    description="FastAPI application for filling Excel templates with data",
    version="0.1.0",
    lifespan=lifespan
)

# 配置 CORS
app.add_middleware(
    CORSMiddleware,
    allow_origins=["*"],  # 在生产环境中应该限制为特定域名
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)

# 获取静态文件目录的绝对路径
static_js_dir = os.path.join(os.path.dirname(os.path.dirname(__file__)), "src", "static","js")
static_dir = os.path.join(os.path.dirname(os.path.dirname(__file__)), "src", "static")
logger.info(f"静态文件目录: {static_dir}")

# 确保静态文件目录存在
if not os.path.exists(static_dir):
    os.makedirs(static_dir)
    logger.info(f"创建静态文件目录: {static_dir}")

# 挂载静态文件目录
app.mount("/js", StaticFiles(directory=static_js_dir), name="js")
app.mount("/static", StaticFiles(directory=static_dir), name="static")
# 注册总路由
app.include_router(api_router, prefix="/api")

# Define the directory where templates are stored
TEMPLATE_DIR = os.path.join(os.path.dirname(os.path.dirname(__file__)), "templates")

# Ensure the template directory exists
if not os.path.exists(TEMPLATE_DIR):
    os.makedirs(TEMPLATE_DIR)
    print(f"Created template directory: {TEMPLATE_DIR}")

# Pydantic models for fill instructions
class PlaceholderFillInstruction(BaseModel):
    type: Literal["placeholder"] = "placeholder"
    data: Dict[str, Any] = Field(..., description="Key-value pairs where key is placeholder name (e.g., 'name') and value is the data to fill.")

class CellFillInstruction(BaseModel):
    type: Literal["cell"] = "cell"
    data: Dict[str, Any] = Field(..., description="Key-value pairs where key is cell address (e.g., 'A1', 'B5') and value is the data to fill.")

FillInstruction = Union[PlaceholderFillInstruction, CellFillInstruction]

class FillRequest(BaseModel):
    """
    Request body for filling a template.
    `template_name`: The name of the built-in template to use (e.g., '通用销售报表.xlsx').
    `sheet_instructions`: Maps sheet names to a list of fill instructions for that sheet.
    """
    template_name: str = Field(..., description="The name of the built-in Excel template file (e.g., '通用销售报表.xlsx').")
    sheet_instructions: Dict[str, List[FillInstruction]] = Field(
        ...,
        description="A dictionary where keys are sheet names (e.g., 'Sheet1', '销售数据') and values are lists of fill instructions for that sheet."
    )

# 示例：添加一个用于获取配置的端点（可选，但方便测试）
@app.get("/config", summary="Get application configuration details (non-sensitive)")
async def get_config():
    """
    Returns non-sensitive application configuration details.
    """
    return {
        "app_name": settings.APP_NAME,
        "debug": settings.DEBUG,
        "cos_region": settings.COS_REGION,
        "cos_bucket_name": settings.COS_BUCKET_NAME,
        "cos_app_id": settings.COS_APP_ID
    }



# 修改接口路径，不再包含 {template_name}


if __name__ == "__main__":
    import uvicorn
    uvicorn.run("src.main:app", host="0.0.0.0", port=8000, reload=True)
